#include "read.h"
#include <QVector2D>
#include <QVector3D>
#include <QDebug>

CRead::CRead(GLFuncName *func)
    : m_func(func)
    , m_indexBuf(QOpenGLBuffer::IndexBuffer)
    , m_vertexShader(QOpenGLShader::Vertex)
    , m_fragmentShader(QOpenGLShader::Fragment)
    , m_texture(QOpenGLTexture::Target2D)
{
    initBuffer();
    initShader();
    initTexture();
}
CRead::~CRead()
{
    m_arrayBuf.destroy();
    m_indexBuf.destroy();
    m_texture.destroy();
}
void CRead::initBuffer()
{
    m_arrayBuf.create();
    m_indexBuf.create();

    ReadPoint();
    ReadFacet();

    m_indexCount = sizeof indices / sizeof(indices[0]);

    m_func->glGenVertexArrays(1, &m_vao);
    m_func->glBindVertexArray(m_vao);

    m_indexBuf.bind();
    m_indexBuf.allocate(indices, sizeof indices);

    m_arrayBuf.bind();
    m_arrayBuf.allocate(vertices, sizeof vertices);

    const int positionLocation = 0;
    m_func->glEnableVertexAttribArray(positionLocation);
    m_func->glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, sizeof (VertexData), nullptr);

    const int texCoordLocation =  1;
    m_func->glEnableVertexAttribArray(texCoordLocation);
    m_func->glVertexAttribPointer(texCoordLocation, 2, GL_FLOAT, GL_FALSE, sizeof(VertexData), (void *)(sizeof (QVector3D)));

    m_func->glBindVertexArray(0);
}

void CRead::initShader()
{
    const auto vShader = u8R"(#version 330 core
layout(location = 0) in vec3 position;
layout(location = 1) in vec2 texCoord;
uniform mat4 mvp;
out vec2 vTexCoord;
void main()
{
    vTexCoord = texCoord;
    gl_Position = mvp * vec4(position, 1.0);
}
)";
    const auto fShader = R"(#version 330 core
uniform sampler2D cubeTexture;
in vec2 vTexCoord;
out vec4 outColor;
void main()
{
    outColor = texture(cubeTexture, vTexCoord);
}
)";
    if (!m_vertexShader.compileSourceCode(vShader)) {
        qWarning() << m_vertexShader.log();
    }
    if (!m_fragmentShader.compileSourceCode(fShader)) {
        qWarning() << m_fragmentShader.log();
    }
}
void CRead::initTexture()
{
    QImage img(":/assets/skin.png");
    m_texture.setData(img.mirrored());
    m_texture.setMinificationFilter(QOpenGLTexture::Nearest);
    m_texture.setMagnificationFilter(QOpenGLTexture::Linear);
    m_texture.setWrapMode(QOpenGLTexture::Repeat);
}

void CRead::ReadPoint()
{

        std::ifstream ifs1;
        ifs1.open(name, std::ios::in);
        std::string buf1;
        getline(ifs1, buf1);
        std::stringstream ss1(buf1);
        while (ss1 >> nP >> nF) {
        }
        double x;
        int i_1 = 0;
        int i_2 = 0;
        std::ifstream ifs;
        ifs.open(name, std::ios::in);
        std::string buf;
        for(int i=0;i<nP;i++){
            if(i%3==0){
                vertices->texCoord.setX(0.0f);
                vertices->texCoord.setX(0.0f);
            }
            else if(i%3==1){
                vertices->texCoord.setX(1.0f);
                vertices->texCoord.setX(0.0);
            }
            else {
                vertices->texCoord.setX(0.0f);
                vertices->texCoord.setX(1.0f);
            }
        }
        while (getline(ifs, buf))
        {
            std::stringstream ss(buf);
            if (i_1 < nP+1)
            {

                while (ss >> x)
                {//每一行包含不同个数的数字
                    if (i_1 ==0)
                        break;
                    else
                    {
                        if (i_2 == 0) {
                           vertices[i_1 - 1].position.setX(x/10);
                           i_2++;
                        }
                        else if (i_2 == 1) {
                            vertices[i_1 - 1].position.setY(x/10);
                            i_2++;
                        }
                        else {
                           vertices[i_1 - 1].position.setZ(x/10);
                            i_2 = 0;
                        }
                    }

                }

                i_1++;
            }
            else
            {
                break;
            }
        }
        ifs.close();
}

void CRead::ReadFacet()
{
        std::ifstream ifs1;
        ifs1.open(name, std::ios::in);
        std::string buf1;
        getline(ifs1, buf1);
        std::stringstream ss1(buf1);
        while (ss1 >> nP >> nF) {
        }
        int i_1 = 0;
        int i_2 = 0;
        std::ifstream ifs;
        ifs.open(name, std::ios::in);
        std::string buf;
        double x;
        double index;
        while (getline(ifs, buf))
        {
            std::stringstream ss(buf);
            if (i_1 >= (nP+1) && i_1 < (nP+nF+1))
            {

                while (ss >> x)
                {//每一行包含不同个数的数字
                    if (i_2 == 0)
                    {
                        index = x;
                        i_2++;
                    }
                    else if (i_2 == 1)
                    {
                        indices[(i_1 - nP-1)*3] = x;
                        i_2++;
                    }
                    else if (i_2 == 2)
                    {
                        indices[(i_1 - nP-1)*3+1] = x;
                        i_2++;
                    }
                    else {
                        indices[(i_1 - nP-1)*3+2]= x;
                        i_2 = 0;
                    }
                }
                i_1++;
            }
            else if (i_1 < nP+1) {
                i_1++;
            }
            else
            {
                break;
            }
        }
        ifs.close();
}
void CRead::draw(QOpenGLShaderProgram &program, const QMatrix4x4 &model, const QMatrix4x4 &view, const QMatrix4x4 &project)
{
    program.removeAllShaders();
    program.addShader(&m_vertexShader);
    program.addShader(&m_fragmentShader);
    if (!program.link()) {
        qWarning() << program.log();
        return;
    }
    if (!program.bind()) {
        qWarning() << program.log();
        return;
    }
    program.setUniformValue("mvp", project * view * model);

    m_texture.bind();
    program.setUniformValue("cubeTexture", 0);

    m_func->glBindVertexArray(m_vao);

    m_func->glDrawElements(GL_TRIANGLES, m_indexCount, GL_UNSIGNED_SHORT, nullptr);
}
